package com.junjie.index12306.biz.wxservice.handler.chatApi;

import cn.hutool.core.util.BooleanUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.junjie.index12306.biz.wxservice.utils.HashUtil;
import com.junjie.index12306.biz.wxservice.utils.RedisUtil;
import com.junjie.index12306.framework.starter.bases.ApplicationContextHolder;
import lombok.Setter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
public class ChatApiTemplate {
    @Autowired
    @Qualifier("chatApiReplyCache")
    private Cache<String, String> chatApiReplyCache;
    @Autowired
    @Qualifier("chatApiAsyncFlagReplyCache")
    private Cache<String, String> chatApiAsyncFlagReplyCache;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private ChatApiFactory chatApiFactory;
    @Autowired
    private QWENChatApi QWENChatApi;
    @Autowired
    private RedisUtil redisUtil;
    @Value("${ChatAI.enabled}")
    private Boolean enabled;

    @Setter
    private ChatApiTemplate chatApiTemplate;

    public String callChatAi(String question,String fromUserName,String MsgId) {
        boolean enabled = Boolean.parseBoolean(redisUtil.get("chat_api_enabled"));
        if (!enabled) return "AI对话功能暂时关闭";

        // 防止一个用户疯狂提问
        String fromUserNameCacheKey = "ai_chat_"+fromUserName;
        boolean setFlag = redisUtil.setNx(fromUserNameCacheKey, 0L, 120L, TimeUnit.SECONDS);

//        RedisTemplate redisTemplate = redisUtil.getRedisTemplate();
//        Long increment = redisTemplate.opsForValue().increment(fromUserNameCacheKey);

        // 如果是第二种对话方式的话，就直接回复随机生成的标识，然后异步通过标识获取答案
        if (question.charAt(2) == '2') {
            if(!setFlag) return "请等待上一个问题生成完毕后，再提问";
            question = question.replace("ai2/", "");
            // 直接判断缓存
            String replyContent = chatApiReplyCache.getIfPresent(question);
            if (StringUtils.hasText(replyContent)) {
                redisUtil.del(fromUserNameCacheKey);
                return replyContent;
            }
            // 生成唯一码
            String originCode = UUID.randomUUID().toString();
            String uniqueCode = HashUtil.hashToBase62(originCode);
            // 异步调用
            chatApiTemplate.asyncChatApi(question, uniqueCode,fromUserNameCacheKey);
            return "唯一码："+uniqueCode+"，有效期为2分钟\n" +
                    "生成需要花费大约20-30秒时间，稍后请输入下方指令获取结果\n" +
                    "获取结果/"+uniqueCode;
        }

        boolean setMsgFlag = false;
        String MsgIdKey = "chat_ai_1_"+MsgId;
        setMsgFlag = redisUtil.setNx(MsgIdKey, 0L, 120L, TimeUnit.SECONDS);

        if((!setFlag)&&(!setMsgFlag)) return "请等待上一个问题生成完毕后，再提问";

        question = question.replace("ai1/", "") + ",大概150个字左右就行了";
        String reply = callChatApi(question);
        redisUtil.del(fromUserNameCacheKey);
        redisUtil.del(MsgIdKey);
        return reply;
    }

    @Async("ChatApiExecutor")
    public void asyncChatApi(String question, String uniqueCode,String fromUserNameCacheKey) {
        chatApiAsyncFlagReplyCache.put(uniqueCode, question);
        callChatApi(question);
        redisUtil.del(fromUserNameCacheKey);
    }

    public String callChatApi(String question) {
        // 先从缓存获取看看
        String cacheKey = question;
        String replyContent = chatApiReplyCache.getIfPresent(cacheKey);
        if (StringUtils.hasText(replyContent)) {
            return replyContent;
        }
        // 分布式锁 锁住相同问题
        RLock lock = redissonClient.getLock(cacheKey);
        lock.lock();
        // 双重判定
        replyContent = chatApiReplyCache.getIfPresent(cacheKey);
        if (StringUtils.hasText(replyContent)) {
            lock.unlock();
            return replyContent;
        }

        try {
            // 暂时只用通义千问API 后序改造成Nacos动态切换 或者数据库+Redis
            ChatApiHandler chatApiHandler = chatApiFactory.getHandlerByChatApiType(ChatApiTypeEnum.QWEN.name());
            String reply = chatApiHandler.dealMsgAndCall(question);
//            String reply = QWENChatApi.callWithMessage(question);
            chatApiReplyCache.put(cacheKey, reply);
            return reply;
        } catch (Exception e) {
            e.printStackTrace();
            return "AI对话出现故障，请联系管理员";
        } finally {
            lock.unlock();
        }
    }

    public String tryGetResult(String uniqueCode) {
        uniqueCode = uniqueCode.replace("获取结果/", "");

        // 判断uniqueCode是否存在
        String question = chatApiAsyncFlagReplyCache.getIfPresent(uniqueCode);
        if (!StringUtils.hasText(question)) return "唯一码不存在或已过期";

        // 可能获取不到问题 获取不到问题就返回继续等待
        String reply = chatApiReplyCache.getIfPresent(question);
        if (!StringUtils.hasText(reply)) return "请稍后获取结果，结果正在生成";

        return reply;
    }


    public static void main(String[] args) {
        String s = "ai1/";
        System.out.println(s.charAt(2));
    }

}
